﻿#region Copyright and License
/*==============================================================================
 *  Copyright (c) cndotnet.org Corporation.  All rights reserved.
 * ===============================================================================
 * This code and information is provided "as is" without warranty of any kind,
 * either expressed or implied, including but not limited to the implied warranties
 * of merchantability and fitness for a particular purpose.
 * ===============================================================================
 * Licensed under the GNU General Public License (GPL) v2
 * http://www.cndotnet.org/ucenter
 * ==============================================================================*/
#endregion
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
using System.Configuration;
using UCenter.Core.Common;

namespace UCenter.Core.Repository
{
    /// <summary>
    /// The base class of repository
    /// </summary>
    public abstract class RepositoryBase
    {
        #region Constructors

        /// <summary>
        /// Initializes a new instance of the <see cref="RepositoryBase"/> class.
        /// </summary>
        protected RepositoryBase()
            : this(DefaultConnectionString, true)
        {
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="RepositoryBase"/> class.
        /// </summary>
        /// <param name="fileOrServerOrConnection">The file or server or connection.</param>
        /// <param name="isReadOnly">if set to <c>true</c> [is read only].</param>
        protected RepositoryBase(string fileOrServerOrConnection, bool isReadOnly)
            : this(new RepositoryContext(fileOrServerOrConnection, isReadOnly))
        {
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="RepositoryBase"/> class.
        /// </summary>
        /// <param name="connection">The connection.</param>
        /// <param name="isReadOnly">if set to <c>true</c> [is read only].</param>
        protected RepositoryBase(IDbConnection connection, bool isReadOnly)
            : this(new RepositoryContext(connection, isReadOnly))
        {
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="RepositoryBase"/> class.
        /// </summary>
        /// <param name="context">The context.</param>
        protected RepositoryBase(RepositoryContext context)
        {
            DataContext = context;
        }

        #endregion

        #region Properties

        /// <summary>
        /// Gets or sets the data context.
        /// </summary>
        /// <value>The data context.</value>
        private RepositoryContext DataContext { get; set; }

        /// <summary>
        /// Gets the context.
        /// </summary>
        /// <value>The context.</value>
        protected IRepositoryContext Context
        {
            get
            {
                return DataContext;
            }
        }

        /// <summary>
        /// Gets or sets a value indicating whether this instance is read only.
        /// </summary>
        /// <value>
        /// 	<c>true</c> if this instance is read only; otherwise, <c>false</c>.
        /// </value>
        public bool IsReadOnly
        {
            get { return Context.IsReadOnly; }
            set { DataContext.ResetContext(value); }
        }

        #endregion

        #region Events

        /// <summary>
        /// Occurs after data saved
        /// </summary>
        public event EventHandler<SavedEventArgs> AfterSaved;

        /// <summary>
        /// Occurs before saved
        /// </summary>
        public event EventHandler<SavedEventArgs> BeforeSaved;

        /// <summary>
        /// Occurs when save failed
        /// </summary>
        public event EventHandler<FailedEventArgs> SaveFailed;

        #endregion

        #region Virtual Methods

        /// <summary>
        /// Called after data saved
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="action">The action.</param>
        protected virtual void OnAfterSaved(Object sender, SaveAction action)
        {
            EventHandler<SavedEventArgs> tempHandler = AfterSaved;
            if (tempHandler != null)
            {
                tempHandler(sender, new SavedEventArgs(sender, action));
            }
        }

        /// <summary>
        /// Called before saved
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="action">The action.</param>
        protected virtual void OnBeforeSaved(Object sender, SaveAction action)
        {
            EventHandler<SavedEventArgs> tempHandler = BeforeSaved;
            if (tempHandler != null)
            {
                tempHandler(sender, new SavedEventArgs(sender, action));
            }
        }

        /// <summary>
        /// Called when save failed
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="exception">The exception.</param>
        protected virtual void OnSaveFailed(Object sender, Exception exception)
        {
            EventHandler<FailedEventArgs> tempHandler = SaveFailed;
            if (tempHandler != null)
            {
                tempHandler(sender, new FailedEventArgs(sender, exception));
            }
        }

        #endregion

        #region Static Properties

        /// <summary>
        /// Gets the name of the repository connection.
        /// </summary>
        /// <returns></returns>
        protected static string GetRepositoryConnectionName()
        {
            string repositoryConnectionName = ConfigurationManager.AppSettings["RepositoryConnectionName"];
            if (string.IsNullOrEmpty(repositoryConnectionName))
            {
                throw new InvalidOperationException("The applicationsetting key 'RepositoryConnectionName' is not set.");
            }
            return repositoryConnectionName;
        }

        /// <summary>
        /// Gets the default connection string.
        /// </summary>
        /// <value>The default connection string.</value>
        protected static string DefaultConnectionString
        {
            get
            {
                return ConfigurationManager.ConnectionStrings[GetRepositoryConnectionName()].ConnectionString;
            }
        }

        #endregion
    }
}
